package logurs

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/robfig/cron/v3"
	"github.com/sirupsen/logrus"
)

type RollingLogger struct {
	*logrus.Logger
	rotateHook *RotateHook
	scheduler  *cron.Cron
	daily      chan struct{}
	stop       chan struct{}
	sighup     chan os.Signal
}

func NewLogger(opts ...Option) *RollingLogger {
	rotateHook := NewRotateHook(opts...)
	logger := logrus.New()
	//添加日志切割hook
	logger.AddHook(rotateHook)
	sighup := make(chan os.Signal, 1)
	//通过系统信号分割
	signal.Notify(sighup, syscall.SIGHUP)
	rollingLogger := &RollingLogger{
		Logger:     logger,
		rotateHook: rotateHook,
		scheduler:  cron.New(cron.WithSeconds()),
		daily:      make(chan struct{}),
		stop:       make(chan struct{}),
		sighup:     sighup,
	}

	rollingLogger.startRotate()
	return rollingLogger
}

func (l *RollingLogger) startRotate() {
	//每天零点定时滚动日志
	l.scheduler.AddFunc("0 0 0 * * ?", l.dailyRote)
	//开启定时任务
	l.scheduler.Start()
	go func() {
		defer func() {
			if err := recover(); err != nil {
				fmt.Fprintf(os.Stderr, "rollingLogger exit with panic(%v)", err)
			}
			if l.scheduler != nil {
				//关闭定时任务
				l.scheduler.Stop()
			}
		}()

		for {
			select {
			case <-l.daily:
				//每日切割
				l.doRotate()
			case <-l.sighup:
				//通过信号切割
				l.doRotate()
			case <-l.stop:
				return
			}
		}
	}()
}

func (l *RollingLogger) dailyRote() {
	l.daily <- struct{}{}
}

func (l *RollingLogger) doRotate() {
	l.rotateHook.doRotate(l.GetLevel())
}

func (l *RollingLogger) Stop() {
	l.stop <- struct{}{}
}
